package agent

import (
	"context"
	"encoding/json"
	"fmt"
	"os"
	"time"

	_ "gitee.com/shiwjlinux/arm/apps"
	"gitee.com/shiwjlinux/arm/apps/instance"
	clients "gitee.com/shiwjlinux/arm/clients/restful"
	"gitee.com/shiwjlinux/arm/common" // Add this import
	"gitee.com/shiwjlinux/arm/conf"
	"gitee.com/shiwjlinux/arm/ioc"
	"github.com/rs/zerolog"
)

var L *zerolog.Logger

func init() {
	ioc.Controller.Registry(AppName, &InstanceAgent{})
	l := conf.C().Log.Logger().With().Str("component", AppName).Logger()
	L = &l
}

func (i *InstanceAgent) Init() error {
	i.logger = L

	return nil
}

func NewResponse() *Response {
	return &Response{
		Data: NewData(),
	}
}

// 容器接口
type Response struct {
	Status  int    `json:"Status"`
	Message string `json:"Message"`
	Data    *Data  `json:"Data"`
}

// NewData 创建新的数据容器
func NewData() *Data {
	return &Data{
		Instances: []*instance.CreateInstanceRequest{},
	}
}

// Data 数据层
type Data struct {
	Instances []*instance.CreateInstanceRequest `json:"Instances"`
}

type InstanceAgent struct {
	client   *clients.Client
	interval time.Duration
	Instance map[string]*instance.Instance
	stopChan chan struct{}
	logger   *zerolog.Logger
	ctx      context.Context
	cancel   context.CancelFunc
	Sn       string `json:"sn" bson:"sn"` // 关联的主机SN
}

func NewInstanceAgent(client *clients.Client, interval time.Duration) (*InstanceAgent, error) {
	ctx, cancel := context.WithCancel(context.Background())
	// logger := conf.C().Logger.GetLogger().With().Str("component", AppName).Logger()
	// logger := conf.C().Log.Logger().With().Str("component", AppName).Logger()
	// logger := Log

	sn, _ := GetHostSn()
	agent := &InstanceAgent{
		client:   client,
		interval: interval,
		Instance: map[string]*instance.Instance{},
		stopChan: make(chan struct{}),
		logger:   L,
		ctx:      ctx,
		cancel:   cancel,
		Sn:       sn,
	}

	// 初始化实例信息
	if err := agent.registerInstances(); err != nil {
		return nil, fmt.Errorf("failed to register instance: %v", err)
	}

	return agent, nil
}

func (a *InstanceAgent) StoreInstance(inst *instance.Instance) error {
	if inst == nil {
		return fmt.Errorf("instance can not be nil")
	}
	if inst.ID == "" {
		return fmt.Errorf("instance ID can not be empty")
	}

	a.Instance[inst.ID] = inst
	a.logger.Debug().
		Str("id=", inst.ID).
		Int("index", inst.Index).
		Str("sn", a.Sn).
		Str("names", inst.Names).
		Str("status ", inst.Status).
		Msg("instance stored successfully")
	return nil
}

// 注册所有实例
func (a *InstanceAgent) registerInstances() error {
	// a.logger.Info().Str("sn", a.Sn).Msg("registering instances")
	// 获取实例信息
	instanceSet := a.CollectInstanceInfo()
	if instanceSet == nil || len(instanceSet.Items) == 0 {
		return fmt.Errorf("no instances found")
	}
	// 清理不存在的key
	a.cleanCache(instanceSet)

	for _, instance := range instanceSet.Items {
		a.logger.Info().
			// Int("num", k+1).
			Int("index", instance.Index).
			Str("sn", a.Sn).
			Str("names", instance.Names).
			Str("id", instance.ID).
			Msg("registering instance")
		if err := a.registerInstance(instance); err != nil {
			a.logger.
				Error().
				Err(err).
				Str("instance id", instance.ID).
				Msg("failed to register instance")
			continue
		}
	}

	return nil
}

// 注册单个实例 ，新增或更新
func (a *InstanceAgent) registerInstance(in *instance.Instance) error {
	// 查询本地缓存，对比hash 如果一致，不处理
	// 先检查本地缓存

	if currentInst, exists := a.Instance[in.ID]; exists {
		// a.logger.Debug().Msgf("a.Instance[in.ID]%s", a.Instance[in.ID])
		// 比较哈希值
		if currentInst.Hash() == in.Hash() {
			a.logger.Debug().
				Str("sn", a.Sn).
				Str("names", in.Names).
				Str("id", in.ID).
				Msg("instance unchanged in local cache")
			return nil
		}
	}

	a.logger.Info().Str("id", in.ID).
		Str("sn", a.Sn).
		Str("names", in.Names).
		Str("id", in.ID).
		Msg("query remote instance")
	// 查询远程服务器，对比hash 如果一致，不处理
	queryReq := instance.NewQueryInstanceRequest().
		WithID(in.ID).
		WithSN(in.Sn)
	set, err := a.client.QueryInstance(a.ctx, queryReq)
	if err != nil {
		return fmt.Errorf("failed to query instance: %v", err)
	}

	// 实例已存在于远程服务器
	if set.Total > 0 {
		remoteInst := set.Items[0]
		// 比较远程实例和新实例的哈希值
		if remoteInst.Hash() == in.Hash() {
			// 实例未发生变化 ，只更新本地缓存
			_ = a.StoreInstance(set.Items[0])

			a.logger.Debug().Str("sn", a.Sn).
				Str("names", in.Names).
				Str("id", in.ID).Msg("instance unchanged in remote server")

			return nil
		}
		a.logger.Debug().Str("sn", a.Sn).
			Str("names", in.Names).
			Str("id", in.ID).
			Str("remote", remoteInst.Hash()).
			Str("local", in.Hash()).
			Msg("instance hash")

		// 实例发生变化，往下走，创建或更新实例
	} else {
		a.logger.Debug().Str("sn", a.Sn).
			Str("names", in.Names).
			Str("id", in.ID).
			Msg("failed to query remote instance")
	}

	// 不存在，创建实例  ； 不一致，更新实例
	a.logger.Info().Str("id", in.ID).Int("index", in.Index).Msg("creating or updating instance")
	createReq := instance.NewInstance().
		FromRequest(in.CreateInstanceRequest).
		WithID(in.ID).
		WithSn(in.Sn).
		WithGameSet(a.List3ThPackages(in.Index))

	// a.logger.Debug().Str("id", createReq.ID).Str("sn", createReq.Sn).Msg("creqteReq")
	createInstance, err := a.client.CreateInstance(a.ctx, createReq)
	if err != nil {
		return fmt.Errorf("failed to create instance: %v", err)
	}
	// 更新本地缓存
	// 不返回错误，因为实例已经创建成功
	_ = a.StoreInstance(createInstance)

	a.logger.Info().
		Str("id", createInstance.ID).
		Msg("instance created successfully")
	return nil
}

func (a *InstanceAgent) Start() {
	a.logger.Info().Msg("starting instance agent")

	// 启动心跳
	go a.runHeartbeatLoop()

	// 启动信息上报
	go a.runReporInstancestLoop()

	// 启动上报APK
	// go a.runReportGamesLoop()
}

func (a *InstanceAgent) cleanCache(set *instance.InstanceSet) error {
	existingIDs := make(map[string]struct{})
	for _, instance := range set.Items {
		existingIDs[instance.ID] = struct{}{}
	}

	for id := range a.Instance {
		if _, exists := existingIDs[id]; !exists {
			delete(a.Instance, id) // 删除不存在的实例
			a.logger.Info().Str("id", id).Msg("remove non-existing instance from cache")
		}
	}
	return nil
}

func (a *InstanceAgent) runReporInstancestLoop() {
	ticker := time.NewTicker(a.interval)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			if err := a.reportInstanceInfo(); err != nil {
				a.logger.Error().Err(err).Msg("failed to report instance info")
			}
		case <-a.stopChan:
			return
		case <-a.ctx.Done():
			return
		}
	}
}

func (a *InstanceAgent) Stop() {
	a.logger.Info().Msg("stopping instance agent")

	// 更新实例状态为停止
	// if a.Instance != nil {
	// 	if err := a.updateInstanceStatus(instance.STATUS_STOPPED); err != nil {
	// 		a.logger.Error().Err(err).Msg("failed to update instance status to stopped")
	// 	}
	// }

	a.cancel() // 取消上下文
	close(a.stopChan)
	a.logger.Info().Msg("instance agent stopped")
}

// isInstanceChanged 检查实例信息是否有变化
func (a *InstanceAgent) isInstanceChanged(current, new *instance.Instance) bool {
	if current == nil || new == nil {
		return true
	}

	return current.Hash() != new.Hash()
}

// 上报实例信息
func (a *InstanceAgent) reportInstanceInfo() error {
	return a.registerInstances()
}

// 收集实例信息
func (a *InstanceAgent) CollectInstanceInfo() *instance.InstanceSet {
	// TODO: 实现实际的实例信息收集逻辑

	set := instance.NewInstanceSet()
	r := NewResponse()
	var armIP string
	if common.IsAndroid() {
		armIP = LocalAgentIp
	} else {
		armIP = TestAgentIp
	}
	c := clients.NewClient(fmt.Sprintf("http://%s:8080", armIP))
	c.Debug(false)
	result, err := c.C.R().SetResult(r).Get("/api/v1/instances")
	if err != nil {
		return nil
	}
	if err := json.Unmarshal(result.Body(), r); err != nil {
		a.logger.Error().Err(err).Msg("")
	}
	if r.Data == nil || len(r.Data.Instances) == 0 {
		a.logger.Err(err).Msgf("Data or Data.Instances nil")
		return nil
	}

	for k, createInstance := range r.Data.Instances {
		// a.logger.Debug().Msgf("(a *InstanceAgent) CollectInstanceInfo() %+v", v)
		hostname, _ := os.Hostname()
		ins := instance.NewInstance().
			WithSn(a.Sn).
			WithHostname(hostname).
			WithUpdatedAt(time.Now().Unix()). // 上报时间
			FromRequest(createInstance).
			WithGameSet(a.List3ThPackages(createInstance.Index))

		set.Items = append(set.Items, ins)
		set.Total = int64(k + 1)
	}

	return set
}
